﻿using System;
using System.Collections.Generic;
using System.Text;
using ParserGenerator.Extensions;
using ParserGenerator.GrammarConstruction;

namespace ParserGenerator.GrammarAnalysis
{
    [Serializable]
    internal sealed class LexicalPrecedenceProfile
    {
        public HashSet<GrammarTerminalSymbol> ShorterTokens { get; }
        public GrammarTerminalSymbol ShorterToken { get; }
        public HashSet<GrammarTerminalSymbol> LongerTokens { get; }

        public LexicalPrecedenceProfile(HashSet<GrammarTerminalSymbol> shorterTokens, GrammarTerminalSymbol shorterToken, HashSet<GrammarTerminalSymbol> longerTokens)
        {
            if (shorterTokens == null)
                throw new ArgumentNullException(nameof(shorterTokens));
            if (longerTokens == null)
                throw new ArgumentNullException(nameof(longerTokens));
            ShorterTokens = shorterTokens;
            ShorterToken = shorterToken;
            LongerTokens = longerTokens;
        }

        private static string FormatTokenSet(HashSet<GrammarTerminalSymbol> tokens)
        {
            if (tokens == null)
                throw new ArgumentNullException(nameof(tokens));
            return "{" + string.Join(", ", tokens) + "}";
        }

        public bool Equals(LexicalPrecedenceProfile other)
        {
            if (other == null)
                return false;
            if (!ShorterTokens.SetEquals(other.ShorterTokens))
                return false;
            if (ShorterToken != other.ShorterToken)
                return false;
            if (!LongerTokens.SetEquals(other.LongerTokens))
                return false;
            return true;
        }

        public sealed override bool Equals(object obj)
        {
            return obj is LexicalPrecedenceProfile && Equals((LexicalPrecedenceProfile)obj);
        }

        public sealed override int GetHashCode()
        {
            int h = ShorterTokens.GetSetHashCode();
            int x = ICollectionExtensions.GetItemHashCode(ShorterToken);
            h = ICollectionExtensions.CombineHashCodes(h, x);
            int y = LongerTokens.GetSetHashCode();
            h = ICollectionExtensions.CombineHashCodes(h, y);
            return h;
        }

        public sealed override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("(");
            sb.Append(FormatTokenSet(ShorterTokens));
            sb.Append(", ");
            if (ShorterToken != null)
                sb.Append(ShorterToken);
            sb.Append(", ");
            sb.Append(FormatTokenSet(LongerTokens));
            sb.Append(")");
            return sb.ToString();
        }
    }
}
